
package de.justphil.tcg.tcgserver.game.mechanics.util.tools.simulation;

import java.util.Random;
import de.justphil.tcg.tcgserver.game.mechanics.config.Config;
import de.justphil.tcg.tcgserver.game.mechanics.game.OnGameProgressListener;
import de.justphil.tcg.tcgserver.game.mechanics.game.OnUserInteractionListener;

public class UserSimulator extends Thread implements OnGameProgressListener {
	
	private static final int			AUTO_KILL_TIME_MS	= 100000;
	private OnUserInteractionListener	onUserInteractionListener;
	private boolean[][]					board;
	private volatile int				player;
	private Random						random;
	private long						startTime;
	private volatile boolean			selectionRequired;
	private volatile boolean			resumeRequired;
	private volatile boolean			stop;
	private final int					selectionTime;
	private final int					confirmTime;
	
	public UserSimulator(long seed, int selectionTime, int confirmTime) {
	
		this.random = new Random(seed);
		board = new boolean[Config.NUM_PLAYERS][Config.NUM_SLOTS_PER_PLAYER];
		selectionRequired = false;
		resumeRequired = false;
		stop = false;
		this.selectionTime = selectionTime;
		this.confirmTime = confirmTime;
	}
	
	@Override
	public void onGameOver(int winner) {
	
		stop = true;
	}
	
	@Override
	public void onGameInfo(int type, String text) {
	
	}
	
	@Override
	public void onProgress(int player, int slot, long cardId, int[] propertyTypes, int life,
			int attack, int defense, int agility) {
	
		if (cardId == -1) {
			board[player][slot] = false;
		}
		else {
			board[player][slot] = true;
		}
	}
	
	@Override
	public void onSelectionRequired(int player, int slot) {
	
		if (selectionTime >= 0) {
			this.player = player;
			selectionRequired = true;
		}
	}
	
	@Override
	public void onResumeRequired(int player) {
	
		if (confirmTime >= 0) {
			resumeRequired = true;
		}
	}
	
	public void setOnUserInteractionListener(OnUserInteractionListener onUserInteractionListener) {
	
		this.onUserInteractionListener = onUserInteractionListener;
	}
	
	@Override
	public void run() {
	
		startTime = System.currentTimeMillis();
		while (!stop && (System.currentTimeMillis() - startTime) < AUTO_KILL_TIME_MS) {
			if (selectionRequired) {
				select();
			}
			else if (resumeRequired) {
				confirm();
			}
			
			synchronized(this) {
				while (!stop && !selectionRequired && !resumeRequired) {
					try {
						this.wait();
					}
					catch (InterruptedException ignored) {
					}
				}
			}
		}
		
	}
	
	private void select() {
	
		selectionRequired = false;
		try {
			Thread.sleep(selectionTime);
		}
		catch (InterruptedException ignored) {
		}
		int enemy = (player + 1) % 2;
		int slot = random.nextInt(board[enemy].length);
		for (int i = 0; i <= board[enemy].length; i++) {
			if (board[enemy][slot]) {
				onUserInteractionListener.onSlotSelected(enemy, slot);
				break;
			}
			slot = (slot + 1) % board[enemy].length;
			assert i < board[enemy].length;
		}
	}
	
	private void confirm() {
	
		resumeRequired = false;
		try {
			Thread.sleep(confirmTime);
		}
		catch (InterruptedException ignored) {
		}
		onUserInteractionListener.onResume();
	}
}
